﻿﻿using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using Dataweb.NShape;
using cz.zcu.PreSti.Shapes;
using Dataweb.NShape.Advanced;
using System.Collections.Generic;
using cz.zcu.PreSti.Guide;

namespace cz.zcu.PreSti.Application
{
    public partial class MainWindow : Form
    {
        private const string modulesDirectory = "modules";
        private Dictionary<string, Symbols> symbols;
        private string tooltipText;
        public MainWindow()
        {
            InitializeComponent();
        }

        public GuideMenuWindow GuideMenuWindow
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        public PresentationWindow PresentationWindow
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        public static DialogResult InputBox(string title, string promptText, ref string value)
        {
            Form form = new Form();
            Label label = new Label();
            TextBox textBox = new TextBox();
            Button buttonOk = new Button();
            Button buttonCancel = new Button();

            form.Text = title;
            label.Text = promptText;
            textBox.Text = value;

            buttonOk.Text = "OK";
            buttonCancel.Text = "Cancel";
            buttonOk.DialogResult = DialogResult.OK;
            buttonCancel.DialogResult = DialogResult.Cancel;

            label.SetBounds(9, 20, 372, 13);
            textBox.SetBounds(12, 36, 372, 20);
            buttonOk.SetBounds(228, 72, 75, 23);
            buttonCancel.SetBounds(309, 72, 75, 23);

            label.AutoSize = true;
            textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
            buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

            form.ClientSize = new Size(396, 107);
            form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
            form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
            form.FormBorderStyle = FormBorderStyle.FixedDialog;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.MinimizeBox = false;
            form.MaximizeBox = false;
            form.AcceptButton = buttonOk;
            form.CancelButton = buttonCancel;

            DialogResult dialogResult = form.ShowDialog();
            value = textBox.Text;
            return dialogResult;
        }

        /// <summary>
        /// Creates a new tab with new display and inserts subdiagram into it.
        /// </summary>
        /// <param name="diagram">diagram supposed to be inserted into new tab</param>
        /// <returns>created new tab</returns>
        private TabPage createTab(Diagram diagram)
        {
            string name = diagram.Name.Substring("Subdiagram ".Length);
            TabPage newTab = new TabPage(name);
            Dataweb.NShape.WinFormsUI.Display newDisplay = createDisplay(name);
            newDisplay.Parent = newTab;
            newDisplay.Diagram = diagram;
            tabControl1.TabPages.Add(newTab);
            symbols.Add(name, new Symbols(newDisplay.Diagram));
            return newTab;
        }

        private TabPage findTab(string text)
        {
            int index = 0;
            while ((index < tabControl1.TabCount) && (!tabControl1.TabPages[index].Text.ToLower().Equals(text.ToLower())))
                index++;
            if (index < tabControl1.TabCount)
                return tabControl1.TabPages[index];
            else
                return null;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            newProject();
        }

        private void display_MouseMove(object sender, MouseEventArgs e)
        {
            Dataweb.NShape.WinFormsUI.Display display = (Dataweb.NShape.WinFormsUI.Display)sender;
            Point p, p2, p3;
            display.ControlToDiagram(e.Location, out p);
            String tooltipText = symbols[display.Name.Substring("display".Length)].GetActualTooltipText(p, out p2);
            if (tooltipText != null)
            {
                if (tooltipText != this.tooltipText)
                {
                    display.DiagramToControl(p2, out p3);
                    toolTip.Show(tooltipText, this, p3.X, p3.Y + 15/*, p3.X + 7, p3.Y - 3*/);
                    this.tooltipText = tooltipText;
                }
            }
            else
            {
                toolTip.Hide(this);
                this.tooltipText = null;
            }

        }

        protected void runToolStripMenuItem_Click(object sender, EventArgs e)
        { 
            foreach (Symbols ss in symbols.Values)
                ss.checkArrows(display1);
            PresentationWindow p = new PresentationWindow(symbols, false);
            p.Show();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveProject();            
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveAsProject();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
           
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (project.IsOpen)
                    if (!closeProject()) return;
                FileInfo fileInfo = new FileInfo(openFileDialog.FileName);
                xmlStore.DirectoryName = fileInfo.Directory.FullName;
                project.Name = fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length);
                xmlStore.FileExtension = fileInfo.Extension;
                try
                {
                    project.Open();
                }
                catch (FileNotFoundException ex)
                {
                    MessageBox.Show("Module " + ex.FileName + " does not found!");
                    return;
                }
                Symbols.createTemplates(project);
                System.Collections.Generic.IEnumerable<Diagram> diagrams = project.Repository.GetDiagrams();
                display1.Diagram = diagrams.First();
                symbols = new Dictionary<string, Symbols>();
                symbols.Add("1", new Symbols(display1.Diagram));
                for (int index = 1; index < diagrams.Count(); index++)
                    createTab(diagrams.ElementAt(index));
                enableMenuItems();
            }
        }

        private void createSubdiagramToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string name = "";
            while (InputBox("Create subdiagram", "Please enter subdiagram name:", ref name) == System.Windows.Forms.DialogResult.OK)
                if (name.Length == 0)
                    MessageBox.Show("Please enter subdiagram name.", "Create subdiagram", MessageBoxButtons.OK, MessageBoxIcon.Information);
                else if (findTab(name) != null)
                    MessageBox.Show("Subdiagram with this name already exists. Please enter another.", "Create subdiagram", MessageBoxButtons.OK, MessageBoxIcon.Information);
                else if (char.IsDigit(name, 0))
                    MessageBox.Show("Name of subdiagram should not begin with digit. Please enter another.", "Create subdiagram", MessageBoxButtons.OK, MessageBoxIcon.Information);
                else
                {
                    //Converts the first character of name to uppercase and creates new subdiagram
                    name = name.Substring(0, 1).ToUpper() + name.Substring(1);
                    createSubdiagram(name);
                    return;
                }
        }

        private void removeSubdiagramToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex > 0)
            {
                string name = tabControl1.SelectedTab.Text;
                if (MessageBox.Show(string.Format("Currently open subdiagram {0} will be removed from projects permanently.\n\nDo you wish to continue?", name), "Remove subdiagram", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                    removeSubdiagram(name);
            }
            else
                MessageBox.Show("Main diagram is currently selected. Main diagram cannot be removed.", "Remove subdiagram", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            closeProject();
        }

        private void newProject()
        {
            project.Name = "New Project";
            project.LibrarySearchPaths.Add(Directory.GetCurrentDirectory() + "\\" + modulesDirectory);
            project.Create();
            project.AddLibraryByName("PrestiShapes", true);

            string[] modules = { };
            if (!Directory.Exists(modulesDirectory)) Directory.CreateDirectory(modulesDirectory);
            modules = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\" + modulesDirectory, "*.dll", SearchOption.AllDirectories);
            foreach (string module in modules)
                project.AddLibraryByFilePath(module, true);

            toolSetController.CreateStandardTools();
            Symbols.createTemplates(project);
            Diagram diagram = new Diagram(string.Format("WebVisits Diagram"));
            diagram.Width = 1000;
            diagram.Height = 1000;
            diagram.BackgroundImageLayout = Dataweb.NShape.ImageLayoutMode.Fit;

            symbols = new Dictionary<string, Symbols>();
            symbols.Add("1", new Symbols(diagram));

            project.Repository.Insert(diagram);
            display1.Diagram = diagram;

            enableMenuItems();
        }

        /// <summary>
        /// Creates a new display and sets it's properties to properly values.
        /// </summary>
        /// <returns>newly created display</returns>
        private Dataweb.NShape.WinFormsUI.Display createDisplay(string name)
        {
            Dataweb.NShape.WinFormsUI.Display display = new Dataweb.NShape.WinFormsUI.Display();
            display.Name = string.Format("display{0}", name);

            display.AllowDrop = display1.AllowDrop;
            display.AutoScroll = display1.AutoScroll;
            display.BackColorGradient = display1.BackColorGradient;
            display.BackgroundGradientAngle = display1.BackgroundGradientAngle;
            display.ConnectionPointShape = display1.ConnectionPointShape;
            display.ControlPointAlpha = display1.ControlPointAlpha;
            display.DiagramSetController = display1.DiagramSetController;
            display.Dock = display1.Dock;
            display.GridAlpha = display1.GridAlpha;
            display.GridColor = display1.GridColor;
            display.GridSize = display1.GridSize;
            display.GripSize = display1.GripSize;
            display.HideDeniedMenuItems = display1.HideDeniedMenuItems;
            display.HighQualityBackground = display1.HighQualityBackground;
            display.HighQualityRendering = display1.HighQualityRendering;
            display.ImeMode = display1.ImeMode;
            display.Location = display1.Location;
            display.MinRotateRange = display1.MinRotateRange;
            display.PropertyController = display1.PropertyController;
            display.RenderingQualityHighQuality = display1.RenderingQualityHighQuality;
            display.RenderingQualityLowQuality = display1.RenderingQualityLowQuality;
            display.ResizeGripShape = display1.ResizeGripShape;
            display.SelectionHilightColor = display1.SelectionHilightColor;
            display.SelectionInactiveColor = display1.SelectionInactiveColor;
            display.SelectionInteriorColor = display1.SelectionInteriorColor;
            display.SelectionNormalColor = display1.SelectionNormalColor;
            display.ShowGrid = display1.ShowGrid;
            display.ShowScrollBars = display1.ShowScrollBars;
            display.Size = display1.Size;
            display.SnapDistance = display1.SnapDistance;
            display.SnapToGrid = display1.SnapToGrid;
            display.ToolPreviewBackColor = display1.ToolPreviewBackColor;
            display.ToolPreviewColor = display1.ToolPreviewColor;
            display.ZoomLevel = display1.ZoomLevel;
            display.ZoomWithMouseWheel = display1.ZoomWithMouseWheel;
            display.MouseMove += new System.Windows.Forms.MouseEventHandler(display_MouseMove);
            display.Validated += new System.EventHandler(display_Validated);

            return display;
        }

        ///<summary>
        ///Creates a new subdiagram and adds it into currently open project.
        ///</summary>
        private void createSubdiagram(string name)
        {
            if (project.IsOpen)
            {
                Diagram subdiagram = new Diagram(string.Format("Subdiagram {0}", name));
                subdiagram.Width = 1000;
                subdiagram.Height = 1000;
                subdiagram.BackgroundImageLayout = Dataweb.NShape.ImageLayoutMode.Fit;
                project.Repository.Insert(subdiagram);
                createTab(subdiagram); //Inserts new subdiagram into new tab
            }
            else
                MessageBox.Show("There is no project open.", "Create subdiagram", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        ///<summary>
        ///Removes a subdiagram, specified by name, from currently open project.
        ///</summary>
        private void removeSubdiagram(string name)
        {
            Diagram subdiagram = project.Repository.GetDiagram(string.Format("Subdiagram {0}", name));
            project.Repository.Delete(subdiagram);
            tabControl1.TabPages.Remove(findTab(name));
        }

        private void saveProject()
        {
            if (((IStoreCache)project.Repository).ProjectId == null) saveAsProject();
            else project.Repository.SaveChanges();
        }

        private void saveAsProject()
        {
            if (saveFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                FileInfo fileInfo = new FileInfo(saveFileDialog.FileName);
                xmlStore.DirectoryName = fileInfo.Directory.FullName;
                xmlStore.ProjectName = fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length);
                xmlStore.FileExtension = fileInfo.Extension;
                if (xmlStore.Exists() && ((IStoreCache)project.Repository).ProjectId == null) xmlStore.Erase();
                project.Repository.SaveChanges();
            }
        }

        private bool closeProject()
        {
            if (project.Repository.IsModified)
                switch (MessageBox.Show("Project is not saved yet.\n\nDo you want to save the project?", "Save project", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
                {
                    case System.Windows.Forms.DialogResult.Yes:
                        saveProject();
                        break;
                    case System.Windows.Forms.DialogResult.Cancel:
                        return false;
                }
            disableMenuItems();
            project.Close();
            while (tabControl1.TabCount > 1)
                tabControl1.TabPages.RemoveAt(tabControl1.TabPages.Count - 1);
            return true;
        }

        private void disableMenuItems()
        {
            runToolStripMenuItem.Enabled = false;
            testToolStripMenuItem.Enabled = false;
            saveAsToolStripMenuItem.Enabled = false;
            saveToolStripMenuItem.Enabled = false;
            closeToolStripMenuItem.Enabled = false;
            createSubdiagramToolStripMenuItem.Enabled = false;
        }

        private void enableMenuItems()
        {
            runToolStripMenuItem.Enabled = true;
            testToolStripMenuItem.Enabled = true;
            saveToolStripMenuItem.Enabled = true;
            saveAsToolStripMenuItem.Enabled = true;
            closeToolStripMenuItem.Enabled = true;
            createSubdiagramToolStripMenuItem.Enabled = true;
        }

        private void testToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Symbols ss in symbols.Values)
                ss.checkArrows(display1);
            PresentationWindow p = new PresentationWindow(symbols, true);
            p.Show();
        }

        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!closeProject()) e.Cancel = true;
        }

        private void display_Validated(object sender, EventArgs e)
        {
            Dataweb.NShape.WinFormsUI.Display display = (Dataweb.NShape.WinFormsUI.Display)sender;
            symbols[display.Name.Substring("display".Length)].checkArrows(display1);
        }

        private void emptyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (project.IsOpen)
                if (!closeProject()) return;
            newProject();
        }          

        private void display1_MouseMove(object sender, MouseEventArgs e)
        {
            Dataweb.NShape.WinFormsUI.Display display = (Dataweb.NShape.WinFormsUI.Display)sender;
            Point p, p2, p3;
            display.ControlToDiagram(e.Location, out p);
            String tooltipText = symbols[display.Name.Substring("display".Length)].GetActualTooltipText(p, out p2);
            if (tooltipText != null)
            {
                if (tooltipText != this.tooltipText)
                {
                    display.DiagramToControl(p2, out p3);
                    toolTip.Show(tooltipText, this, p3.X, p3.Y + 15/*, p3.X + 7, p3.Y - 3*/);
                    this.tooltipText = tooltipText;
                }
            }
            else
            {
                toolTip.Hide(this);
                this.tooltipText = null;
            }
        }

        private void display1_Validated(object sender, EventArgs e)
        {
            Dataweb.NShape.WinFormsUI.Display display = (Dataweb.NShape.WinFormsUI.Display)sender;
            symbols[display.Name.Substring("display".Length)].checkArrows(display1);
        }

        private void templatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (project.IsOpen)
                if (!closeProject()) return;
            newProject();
            GuideMenuWindow scenarioGuideMenuWindow = new GuideMenuWindow(project, display1.Diagram, this);            
            scenarioGuideMenuWindow.Show();
        }

        public void Launch()
        {
            runToolStripMenuItem_Click(new object(), new EventArgs());
        }

        private void randomToolStripMenuItem_Click(object sender, EventArgs e)
        {

            
        }

        private void sequentialToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
    }
}